#include "UdxDataset.h"
#include <vector>
#include <algorithm>

#include <emscripten/bind.h>
using namespace emscripten;
using namespace NGIS::Data;

#include <wchar.h>
#include <locale.h>

namespace NGIS
{
	namespace Data
	{
		bool CUdxDataset::LoadFromXmlFile(const char* fileName)
		{
			tinyxml2::XMLDocument doc;
			doc.LoadFile( fileName );
			tinyxml2::XMLElement* rootEle = doc.RootElement();
			
			for (tinyxml2::XMLElement* ele=rootEle->FirstChildElement(); ele; ele=ele->NextSiblingElement())
			{
				ParseXDO((CUdxNode*)this, ele);
			}

			return true;
		}

		bool CUdxDataset::FormatToXmlFile(const char* fileName)
		{
			tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
			tinyxml2::XMLElement* element = doc->NewElement("dataset");
			doc->LinkEndChild(element);

			int count = this->getChildNodeCount();
			for (int iNode=0; iNode<count; iNode++)
			{
				IUdxNode* tempNode = this->getChildNode(iNode);
				FormatXDO(tempNode, element);
			}

			doc->SaveFile(fileName);
			delete doc;

			return true;
		}

		bool CUdxDataset::LoadFromXmlStream(const char* xmlStr)
		{
			tinyxml2::XMLDocument doc;
			doc.Parse( xmlStr );
			tinyxml2::XMLElement* rootEle = doc.RootElement();

			for (tinyxml2::XMLElement* ele=rootEle->FirstChildElement(); ele; ele=ele->NextSiblingElement())
			{
				ParseXDO((CUdxNode*)this, ele);
			}

			return true;
		}

		bool CUdxDataset::FormatToXmlStream(std::string& xmlStr)
		{
			tinyxml2::XMLDocument doc;
			tinyxml2::XMLElement* element = doc.NewElement("dataset");
			doc.LinkEndChild(element);

			int count = this->getChildNodeCount();
			for (int iNode=0; iNode<count; iNode++)
			{
				IUdxNode* tempNode = this->getChildNode(iNode);
				FormatXDO(tempNode, element);
			}

			tinyxml2::XMLPrinter printer;
			doc.Print(&printer);
			
			xmlStr = printer.CStr();
			return true;
		}

		void split(const std::string& s, const std::string& delim, std::vector<std::string>* ret) 
		{  
			size_t last = 0;   
			size_t index=s.find_first_of(delim,last);  
			while (index!=std::string::npos)  
			{   
				ret->push_back(s.substr(last,index-last));   
				last=index+1;    
				index=s.find_first_of(delim,last);  
			}   
			if (index-last>0)  
			{     
				ret->push_back(s.substr(last,index-last));
			}
		}

		void CUdxDataset::ParseXDO(IUdxNode* containerNode, tinyxml2::XMLElement* element)
		{
			std::string typeStr = element->Attribute("kernelType");
			const char* name = element->Attribute("name");
			EKernelType kernelType = String2KernelType(typeStr.c_str());

			if (typeStr == "int")
			{
				int val = element->IntAttribute("value");
				IUdxNode* node = containerNode->addChildNode(name, kernelType);
				CUdxKernelIntValue* realKernel = (CUdxKernelIntValue*)node->getKernel();
				realKernel->setTypedValue(val);
			}
			else if (typeStr == "real")
			{
				double val = element->DoubleAttribute("value");
				IUdxNode* node = containerNode->addChildNode(name, kernelType);
				CUdxKernelRealValue* realKernel = (CUdxKernelRealValue*)node->getKernel();
				realKernel->setTypedValue(val);
			}
			else if (typeStr == "string")
			{
				const char* val = element->Attribute("value");
				IUdxNode* node = containerNode->addChildNode(name, kernelType);
				CUdxKernelStringValue* realKernel = (CUdxKernelStringValue*)node->getKernel();
				realKernel->setTypedValue(val);
			}
			else if (typeStr == "vector2d")
			{
				const char* valStr = element->Attribute("value");
				IUdxNode* node = containerNode->addChildNode(name, kernelType);
				CUdxKernelVector2dValue* realKernel = (CUdxKernelVector2dValue*)node->getKernel();
				double x, y;
				sscanf(valStr, "%lf,%lf", &x, &y);
				realKernel->setTypedValue(x, y);
			}
			else if (typeStr == "vector3d")
			{
				const char* valStr = element->Attribute("value");
				IUdxNode* node = containerNode->addChildNode(name, kernelType);
				CUdxKernelVector3dValue* realKernel = (CUdxKernelVector3dValue*)node->getKernel();
				double x, y, z;
				sscanf(valStr, "%lf,%lf,%lf", &x, &y, &z);
				realKernel->setTypedValue(x, y, z);
			}
			else if (typeStr == "vector4d")
			{
				const char* valStr = element->Attribute("value");
				IUdxNode* node = containerNode->addChildNode(name, kernelType);
				CUdxKernelVector4dValue* realKernel = (CUdxKernelVector4dValue*)node->getKernel();
				double x, y, z, m;
				sscanf(valStr, "%lf,%lf,%lf,%lf", &x, &y, &z, &m);
				realKernel->setTypedValue(x, y, z, m);
			}
			else if (typeStr == "int_array")
			{
				std::string valStr = element->Attribute("value");
				std::vector<std::string> ret;
				split(valStr, ",", &ret);
				int count = ret.size();
				{
					IUdxNode* node = containerNode->addChildNode(name, kernelType);
					CUdxKernelIntArray* realKernel = (CUdxKernelIntArray*)node->getKernel();
					for (int iVal=0; iVal<count; iVal++)
					{
						realKernel->addTypedValue(atoi(ret[iVal].c_str()));
					}
				}
			}
			else if (typeStr == "real_array")
			{
				std::string valStr = element->Attribute("value");
				std::vector<std::string> ret;
				split(valStr, ",", &ret);
				int count = ret.size();
				{
					IUdxNode* node = containerNode->addChildNode(name, kernelType);
					CUdxKernelRealArray* realKernel = (CUdxKernelRealArray*)node->getKernel();
					for (int iVal=0; iVal<count; iVal++)
					{
						realKernel->addTypedValue(atof(ret[iVal].c_str()));
					}
				}
			}
			else if (typeStr == "string_array")
			{
				std::string valStr = element->Attribute("value");
				std::vector<std::string> ret;
				split(valStr, ";", &ret);
				int count = ret.size();
				{
					IUdxNode* node = containerNode->addChildNode(name, kernelType);
					CUdxKernelStringArray* realKernel = (CUdxKernelStringArray*)node->getKernel();
					for (int iVal=0; iVal<count; iVal++)
					{
						realKernel->addTypedValue(ret[iVal].c_str());
					}
				}
			}
			else if (typeStr == "vector2d_array")
			{
				std::string valStr = element->Attribute("value");
				std::vector<std::string> ret;
				split(valStr, ";", &ret);
				int count = ret.size();
				{
					IUdxNode* node = containerNode->addChildNode(name, kernelType);
					CUdxKernelVector2dArray* realKernel = (CUdxKernelVector2dArray*)node->getKernel();
					for (int iVal=0; iVal<count; iVal++)
					{
						double x, y;
						sscanf(ret[iVal].c_str(), "%lf,%lf", &x, &y);
						realKernel->addTypedValue(x, y);
					}
				}
			}
			else if (typeStr == "vector3d_array")
			{
				const char* valStr = element->Attribute("value");
				std::vector<std::string> ret;
				split(valStr, ";", &ret);
				int count = ret.size();
				{
					IUdxNode* node = containerNode->addChildNode(name, kernelType);
					CUdxKernelVector3dArray* realKernel = (CUdxKernelVector3dArray*)node->getKernel();
					for (int iVal=0; iVal<count; iVal++)
					{
						double x, y, z;
						sscanf(ret[iVal].c_str(), "%lf,%lf,%lf", &x, &y, &z);
						realKernel->addTypedValue(x, y, z);
					}
				}
			}
			else if (typeStr == "vector4d_array")
			{
				std::string valStr = element->Attribute("value");
				std::vector<std::string> ret;
				split(valStr, ";", &ret);
				int count = ret.size();
				{
					IUdxNode* node = containerNode->addChildNode(name, kernelType);
					CUdxKernelVector4dArray* realKernel = (CUdxKernelVector4dArray*)node->getKernel();
					for (int iVal=0; iVal<count; iVal++)
					{
						double x, y, z, m;
						sscanf(ret[iVal].c_str(), "%lf,%lf,%lf,%lf", &x, &y, &z, &m);
						realKernel->addTypedValue(x, y, z, m);
					}
				}
			}
			else if (typeStr == "any" ||
					  typeStr == "list" ||
					  typeStr == "map" ||
					  typeStr == "table")
			{
				IUdxNode* node = containerNode->addChildNode(name, kernelType);
				for (tinyxml2::XMLElement* childEle = element->FirstChildElement(); childEle; childEle = childEle->NextSiblingElement())
				{
					ParseXDO(node, childEle);
				}
			}
			
		}

		void CUdxDataset::FormatXDO(IUdxNode* pNode, tinyxml2::XMLElement* element)
		{
			EKernelType kernelType = pNode->getKernel()->getType();
			const char* name = pNode->getName();
			tinyxml2::XMLDocument* doc = element->GetDocument();
			tinyxml2::XMLElement* childEle = doc->NewElement("XDO");
			element->LinkEndChild(childEle);
			childEle->SetAttribute("name", name);
			if (kernelType == EKernelType::EKT_INT)
			{
				{
					IUdxKernelIntValue* realKernel = (IUdxKernelIntValue*)pNode->getKernel();
					int val = realKernel->getTypedValue();
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", val);
				}
			}
			else if (kernelType == EKernelType::EKT_REAL)
			{
				{
					IUdxKernelRealValue* realKernel = (IUdxKernelRealValue*)pNode->getKernel();
					double val = realKernel->getTypedValue();
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", val);
				}
			}
			else if (kernelType == EKernelType::EKT_STRING)
			{
				{
					IUdxKernelStringValue* realKernel = (IUdxKernelStringValue*)pNode->getKernel();
					std::string val = realKernel->getTypedValue();
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", val.c_str());
				}
			}
			else if (kernelType == EKernelType::EKT_VECTOR2)
			{
				{
					IUdxKernelVector2dValue* realKernel = (IUdxKernelVector2dValue*)pNode->getKernel();
					Vector2d v = realKernel->getTypedValue();
					char vector2dStr[100];
					sprintf(vector2dStr, "%f,%f", v.x, v.y);
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", vector2dStr);
				}
			}
			else if (kernelType == EKernelType::EKT_VECTOR3)
			{
				{
					IUdxKernelVector3dValue* realKernel = (IUdxKernelVector3dValue*)pNode->getKernel();
					Vector3d v =realKernel->getTypedValue();
					char vector3dStr[100];
					sprintf(vector3dStr, "%f,%f,%f", v.x, v.y, v.z);
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", vector3dStr);
				}
			}
			else if (kernelType == EKernelType::EKT_VECTOR4)
			{
				{
					IUdxKernelVector4dValue* realKernel = (IUdxKernelVector4dValue*)pNode->getKernel();
					Vector4d v =realKernel->getTypedValue();
					char vector4dStr[100];
					sprintf(vector4dStr, "%f,%f,%f,%f", v.x, v.y, v.z, v.m);
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", vector4dStr);
				}
			}
			else if (kernelType == (EKernelType)(EKernelType::EKT_INT|EKernelType::EKT_LIST))
			{
				{
					IUdxKernelIntArray* realKernel = (IUdxKernelIntArray*)pNode->getKernel();
					int count = realKernel->getCount();
					std::string valStr = "";
					for (int iVal=0; iVal<count; iVal++)
					{
						int val = 0;
						if (realKernel->getTypedValueByIndex(iVal, val)==false)
							continue;
						char tempValChar[100];
						if (iVal!=count-1)
							sprintf(tempValChar, "%d, ", val);
						else
							sprintf(tempValChar, "%d", val);
						valStr += tempValChar;
					}
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", valStr.c_str());
				}
			}
			else if (kernelType == (EKernelType)(EKernelType::EKT_REAL|EKernelType::EKT_LIST))
			{
				{
					IUdxKernelRealArray* realKernel = (IUdxKernelRealArray*)pNode->getKernel();
					int count = realKernel->getCount();
					std::string valStr = "";
					for (int iVal=0; iVal<count; iVal++)
					{
						double val = 0;
						if (realKernel->getTypedValueByIndex(iVal, val)==false)
							continue;
						char tempValChar[100];
						if (iVal!=count-1)
							sprintf(tempValChar, "%lf, ", val);
						else
							sprintf(tempValChar, "%lf", val);
						valStr += tempValChar;
					}
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", valStr.c_str());
				}
			}
			else if (kernelType == (EKernelType)(EKernelType::EKT_STRING|EKernelType::EKT_LIST))
			{
				{
					IUdxKernelStringArray* realKernel = (IUdxKernelStringArray*)pNode->getKernel();
					int count = realKernel->getCount();
					std::string valStr = "";
					for (int iVal=0; iVal<count; iVal++)
					{
						std::string val = 0;
						if (realKernel->getTypedValueByIndex(iVal, val)==false)
							continue;
						char tempValChar[100];
						if (iVal!=count-1)
						{
							valStr += val;
							valStr += "; ";
						}
						else
							valStr += val;
					}
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", valStr.c_str());
				}
			}
			else if (kernelType == (EKernelType)(EKernelType::EKT_VECTOR2|EKernelType::EKT_LIST))
			{
				{
					IUdxKernelVector2dArray* realKernel = (IUdxKernelVector2dArray*)pNode->getKernel();
					int count = realKernel->getCount();
					std::string valStr = "";
					for (int iVal=0; iVal<count; iVal++)
					{
						Vector2d val;
						if (realKernel->getTypedValueByIndex(iVal, val)==false)
							continue;
						char tempValChar[100];
						if (iVal!=count-1)
						{
							sprintf(tempValChar, "%lf,%lf; ", val.x, val.y);
						}
						else
							sprintf(tempValChar, "%lf,%lf", val.x, val.y);
						valStr += tempValChar;
					}
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", valStr.c_str());
				}
			}
			else if (kernelType == (EKernelType)(EKernelType::EKT_VECTOR3|EKernelType::EKT_LIST))
			{
				{
					IUdxKernelVector3dArray* realKernel = (IUdxKernelVector3dArray*)pNode->getKernel();
					int count = realKernel->getCount();
					std::string valStr = "";
					for (int iVal=0; iVal<count; iVal++)
					{
						Vector3d val;
						if (realKernel->getTypedValueByIndex(iVal, val)==false)
							continue;
						char tempValChar[100];
						if (iVal!=count-1)
						{
							sprintf(tempValChar, "%lf,%lf,%lf; ", val.x, val.y, val.z);
						}
						else
							sprintf(tempValChar, "%lf,%lf,%lf", val.x, val.y, val.z);
						valStr += tempValChar;
					}
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", valStr.c_str());
				}
			}
			else if (kernelType == (EKernelType)(EKernelType::EKT_VECTOR4|EKernelType::EKT_LIST))
			{
				{
					IUdxKernelVector4dArray* realKernel = (IUdxKernelVector4dArray*)pNode->getKernel();
					int count = realKernel->getCount();
					std::string valStr = "";
					for (int iVal=0; iVal<count; iVal++)
					{
						Vector4d val;
						if (realKernel->getTypedValueByIndex(iVal, val)==false)
							continue;
						char tempValChar[100];
						if (iVal!=count-1)
						{
							sprintf(tempValChar, "%lf,%lf,%lf,%lf; ", val.x, val.y, val.z, val.m);
						}
						else
							sprintf(tempValChar, "%lf,%lf,%lf,%lf", val.x, val.y, val.z, val.m);
						valStr += tempValChar;
					}
					childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
					childEle->SetAttribute("value", valStr.c_str());
				}
			}
			else if (kernelType == EKernelType::EKT_NODE ||
					   kernelType == EKernelType::EKT_LIST || 
					   kernelType == EKernelType::EKT_MAP ||
					   kernelType == EKernelType::EKT_TABLE)
			{
				childEle->SetAttribute("kernelType", KernelType2String(kernelType).c_str());
				int count = pNode->getChildNodeCount();
				for (int iNode=0; iNode<count; iNode++)
				{
					IUdxNode* tempNode = pNode->getChildNode(iNode);
					FormatXDO(tempNode, childEle);
				}
			}
		}

		bool CUdxDataset::LoadFromJsonFile(const char* fileName)
		{
			return false;
		}

		bool CUdxDataset::FormatToJsonFile(const char* fileName)
		{
			return false;
		}

		bool CUdxDataset::LoadFromJsonStream(const char* jsonStr)
		{
			return false;
		}

		bool CUdxDataset::FormatToJsonStream(std::string& jsonStr)
		{
			return false;
		}

		bool CUdxDataset::constructDataFromSchema( Schema::IUdxNodeSchema* pSNode )
		{
			for (int i = 0; i < pSNode->getChildNodeCount(); i++)
			{
				Schema::IUdxNodeSchema* tempSNode = pSNode->getChildNode(i);
				std::string name = tempSNode->getName();
				Schema::ESchemaNodeType pSType = tempSNode->getDescription()->getKernelType();
				EKernelType pDType = getKernelTypeBySchema(pSType);
				IUdxNode* tempDNode = this->addChildNode(name.c_str(), pDType);
				IterateChildNodes(tempSNode, tempDNode);
			}
			return true;
		}

	}
}

std::string ws2s(const std::wstring& ws)  
{  
	std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";  

	setlocale(LC_ALL, "chs");  

	const wchar_t* _Source = ws.c_str();  
	size_t _Dsize = 2 * ws.size() + 1;  
	char *_Dest = new char[_Dsize];  
	memset(_Dest,0,_Dsize);  
	wcstombs(_Dest,_Source,_Dsize);  
	std::string result = _Dest;  
	delete []_Dest;  

	setlocale(LC_ALL, curLocale.c_str());  

	return result;  
}  

std::wstring s2ws(const std::string& s)  
{  
	setlocale(LC_ALL, "chs");  

	const char* _Source = s.c_str();  
	size_t _Dsize = s.size() + 1;  
	wchar_t *_Dest = new wchar_t[_Dsize];  
	wmemset(_Dest, 0, _Dsize);  
	mbstowcs(_Dest,_Source,_Dsize);  
	std::wstring result = _Dest;  
	delete []_Dest;  

	setlocale(LC_ALL, "C");  

	return result;  
} 


//////////////////////////////////////////////////////////////////////////
//
//
//
//////////////////////////////////////////////////////////////////////////
float getVersion()
{
	return 1.0;
};

int createDataset()
{
	IUdxDataset* pDataset = new CUdxDataset("dataset");
	return (int)pDataset;
};

int getDatasetNode(int dxID)
{
	IUdxDataset* parentNode = (IUdxDataset*)dxID;
	IUdxNode* pNode = static_cast<IUdxNode*>(parentNode);
	return (int)pNode;
};

//////////////////////////////////////////////////////////////////////////
int getNodeChildCount(int nxID)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	return pNode->getChildNodeCount();
};

int getChildNode(int nxID, int idx)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	int count = pNode->getChildNodeCount();
	if (idx < 0 || idx >= count)
		return 0;
	return (int)(pNode->getChildNode(idx));
}

std::string getNodeName(int nxID)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	return pNode->getName();
}

bool setNodeName(int nxID, std::string pName)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	pNode->setName(pName.c_str());
}

EKernelType getNodeType(int nxID)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	return pNode->getKernel()->getType();
}

int getNodeLength(int nxID)
{
	return 0;
}


std::string kerneltype2string(EKernelType pType)
{
	return KernelType2String(pType);
}

EKernelType string2kerneltype(std::string pStr)
{
	return String2KernelType(pStr);
}

//////////////////////////////////////////////////////////////////////////
//
//
//
//////////////////////////////////////////////////////////////////////////

int addChildNode(int nxID, std::string name, EKernelType type)
{
	IUdxNode* parentNode = (IUdxNode*)nxID;
	IUdxNode* pNode = parentNode->addChildNode(name.c_str(), type);
	return (int)pNode;
};

bool setIntNodeValue(int nxID, int value)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_INT)
		return false;
	IUdxKernelIntValue* realKernel = (IUdxKernelIntValue*)pNode->getKernel();
	realKernel->setTypedValue(value);
	return true;
};

bool setRealNodeValue(int nxID, double value)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_REAL)
		return false;
	IUdxKernelRealValue* realKernel = (IUdxKernelRealValue*)pNode->getKernel();
	realKernel->setTypedValue(value);
	return true;
};

bool setStringNodeValue(int nxID, std::string value)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_STRING)
		return false;
	IUdxKernelStringValue* realKernel = (IUdxKernelStringValue*)pNode->getKernel();
	realKernel->setTypedValue(value);
	return true;
};

bool setVector2dNodeValue(int nxID, double x, double y)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR2)
		return false;
	IUdxKernelVector2dValue* realKernel = (IUdxKernelVector2dValue*)pNode->getKernel();
	realKernel->setTypedValue(x, y);
	return true;
};

bool setVector3dNodeValue(int nxID, double x, double y, double z)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR3)
		return false;
	IUdxKernelVector3dValue* realKernel = (IUdxKernelVector3dValue*)pNode->getKernel();
	realKernel->setTypedValue(x, y, z);
	return true;
};

bool setVector4dNodeValue(int nxID, double x, double y, double z, double m)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR4)
		return false;
	IUdxKernelVector4dValue* realKernel = (IUdxKernelVector4dValue*)pNode->getKernel();
	realKernel->setTypedValue(x, y, z, m);
	return true;
};

//////////////////////////////////////////////////////////////////////////
bool addIntNodeValue(int nxID, int value, int idx)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_INT_LIST)
		return false;
	IUdxKernelIntArray* realKernel = (IUdxKernelIntArray*)pNode->getKernel();
	if (realKernel->getCount() > idx)
	{
		realKernel->setTypedValue(value, idx);
	}
	else
	{
		realKernel->addTypedValue(value);
	}
	return true;
};

bool addRealNodeValue(int nxID, double value, int idx)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_REAL_LIST)
		return false;
	IUdxKernelRealArray* realKernel = (IUdxKernelRealArray*)pNode->getKernel();
	if (realKernel->getCount() > idx)
	{
		realKernel->setTypedValue(value, idx);
	}
	else
	{
		realKernel->addTypedValue(value);
	}
	return true;
};

bool addStringNodeValue(int nxID, std::string value, int idx)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_STRING_LIST)
		return false;
	IUdxKernelStringArray* realKernel = (IUdxKernelStringArray*)pNode->getKernel();
	if (realKernel->getCount() > idx)
	{
		realKernel->setTypedValue(value, idx);
	}
	else
	{
		realKernel->addTypedValue(value);
	}
	return true;
};

bool addVector2dNodeValue(int nxID, double x, double y, int idx)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR2_LIST)
		return false;
	IUdxKernelVector2dArray* realKernel = (IUdxKernelVector2dArray*)pNode->getKernel();
	if (realKernel->getCount() > idx)
	{
		realKernel->setTypedValue(Vector2d(x, y), idx);
	}
	else
	{
		realKernel->addTypedValue(x, y);
	}
	return true;
};

bool addVector3dNodeValue(int nxID, double x, double y, double z, int idx)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR3_LIST)
		return false;
	IUdxKernelVector3dArray* realKernel = (IUdxKernelVector3dArray*)pNode->getKernel();
	if (realKernel->getCount() > idx)
	{
		realKernel->setTypedValue(Vector3d(x, y, z), idx);
	}
	else
	{
		realKernel->addTypedValue(x, y, z);
	}
	return true;
};

bool addVector4dNodeValue(int nxID, double x, double y, double z, double m, int idx)
{
	IUdxNode* pNode = (IUdxNode*)nxID;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR4_LIST)
		return false;
	IUdxKernelVector4dArray* realKernel = (IUdxKernelVector4dArray*)pNode->getKernel();
	if (realKernel->getCount() > idx)
	{
		realKernel->setTypedValue(Vector4d(x, y, z, m), idx);
	}
	else
	{
		realKernel->addTypedValue(x, y, z, m);
	}
	return true;
};

//////////////////////////////////////////////////////////////////////////
int getNodeIntValue(int node)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_INT)
		return false;
	IUdxKernelIntValue* realKernel = (IUdxKernelIntValue*)pNode->getKernel();
	return realKernel->getTypedValue();
}

double getNodeRealValue(int node)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_REAL)
		return false;
	IUdxKernelRealValue* realKernel = (IUdxKernelRealValue*)pNode->getKernel();
	return realKernel->getTypedValue();
}

std::string getNodeStringValue(int node)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_STRING)
		return "";
	IUdxKernelStringValue* realKernel = (IUdxKernelStringValue*)pNode->getKernel();
	return realKernel->getTypedValue();
}

Vector2d getNodeVector2dValue(int node)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR2)
		return Vector2d(0,0);
	IUdxKernelVector2dValue* realKernel = (IUdxKernelVector2dValue*)pNode->getKernel();
	return realKernel->getTypedValue();
}

Vector3d getNodeVector3dValue(int node)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR3)
		return Vector3d(0,0,0);
	IUdxKernelVector3dValue* realKernel = (IUdxKernelVector3dValue*)pNode->getKernel();
	return realKernel->getTypedValue();
}

Vector4d getNodeVector4dValue(int node)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR4)
		return Vector4d(0,0,0,0);
	IUdxKernelVector4dValue* realKernel = (IUdxKernelVector4dValue*)pNode->getKernel();
	return realKernel->getTypedValue();
}

//////////////////////////////////////////////////////////////////////////
int getNodeIntArrayValue(int node, int idx)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_INT_LIST)
		return false;
	IUdxKernelIntArray* realKernel = (IUdxKernelIntArray*)pNode->getKernel();
	int retVal = 0;
	realKernel->getTypedValueByIndex(idx, retVal);
	return retVal;
}

double getNodeRealArrayValue(int node, int idx)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_REAL_LIST)
		return 0.0;
	IUdxKernelRealArray* realKernel = (IUdxKernelRealArray*)pNode->getKernel();
	double retVal = 0.0;
	realKernel->getTypedValueByIndex(idx, retVal);
	return retVal;
}

std::string getNodeStringArrayValue(int node, int idx)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_STRING_LIST)
		return "";
	IUdxKernelStringArray* realKernel = (IUdxKernelStringArray*)pNode->getKernel();
	std::string retVal = "";
	realKernel->getTypedValueByIndex(idx, retVal);
	return retVal;
}

Vector2d getNodeVector2dArrayValue(int node, int idx)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR2_LIST)
		return Vector2d(0,0);
	IUdxKernelVector2dArray* realKernel = (IUdxKernelVector2dArray*)pNode->getKernel();
	Vector2d retVal; 
	realKernel->getTypedValueByIndex(idx, retVal);
	return retVal;
}

Vector3d getNodeVector3dArrayValue(int node, int idx)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR3_LIST)
		return Vector3d(0,0,0);
	IUdxKernelVector3dArray* realKernel = (IUdxKernelVector3dArray*)pNode->getKernel();
	Vector3d retVal; 
	realKernel->getTypedValueByIndex(idx, retVal);
	return retVal;
}

Vector4d getNodeVector4dArrayValue(int node, int idx)
{
	IUdxNode* pNode = (IUdxNode*)node;
	if (pNode->getKernel()->getType() != EKernelType::EKT_VECTOR4_LIST)
		return Vector4d(0,0,0,0);
	IUdxKernelVector4dArray* realKernel = (IUdxKernelVector4dArray*)pNode->getKernel();
	Vector4d retVal; 
	realKernel->getTypedValueByIndex(idx, retVal);
	return retVal;
}

//////////////////////////////////////////////////////////////////////////
//
//
//
//////////////////////////////////////////////////////////////////////////

std::string udx_formatToXmlStr(int dxObj)
{
	std::string xml_str = "";
	IUdxDataset* pNode = (IUdxDataset*)dxObj;
	pNode->FormatToXmlStream(xml_str);

	return xml_str;
}

bool udx_loadFromXmlStr(int dxObj, std::string xml_str)
{
	IUdxDataset* pNode = (IUdxDataset*)dxObj;
	if (pNode->LoadFromXmlStream(xml_str.c_str()))
		return true;
	else
		return false;
}












EMSCRIPTEN_BINDINGS(udx_data_module) {
	enum_<EKernelType>("KernelType")
		.value("EKT_NULL", EKT_NULL)
		.value("EKT_INT", EKT_INT)
		.value("EKT_REAL", EKT_REAL)
		.value("EKT_STRING", EKT_STRING)
		.value("EKT_VECTOR2", EKT_VECTOR2)
		.value("EKT_VECTOR3", EKT_VECTOR3)
		.value("EKT_VECTOR4", EKT_VECTOR4)
		.value("EKT_NODE", EKT_NODE)
		.value("EKT_LIST", EKT_LIST)
		.value("EKT_MAP", EKT_MAP)
		.value("EKT_TABLE", EKT_TABLE)
		.value("EKT_INT_LIST", EKT_INT_LIST)
		.value("EKT_REAL_LIST", EKT_REAL_LIST)
		.value("EKT_STRING_LIST", EKT_STRING_LIST)
		.value("EKT_VECTOR2_LIST", EKT_VECTOR2_LIST)
		.value("EKT_VECTOR3_LIST", EKT_VECTOR3_LIST)
		.value("EKT_VECTOR4_LIST", EKT_VECTOR4_LIST)
		.value("EKT_COUNT", EKT_COUNT)
		;

	value_array<Vector2d>("Vector2d")
		.element(&Vector2d::x)
		.element(&Vector2d::y)
		;

	value_array<Vector3d>("Vector3d")
		.element(&Vector3d::x)
		.element(&Vector3d::y)
		.element(&Vector3d::z)
		;

	value_array<Vector4d>("Vector4d")
		.element(&Vector4d::x)
		.element(&Vector4d::y)
		.element(&Vector4d::z)
		.element(&Vector4d::m)
		;

	function("getVersion", &getVersion);
	function("createDataset", &createDataset);
	function("getDatasetNode", &getDatasetNode);

	function("getNodeChildCount", &getNodeChildCount);
	function("getChildNode", &getChildNode);
	function("getNodeName", &getNodeName);
	function("setNodeName", &setNodeName);
	function("getNodeType", &getNodeType);
	function("getNodeLength", &getNodeLength);
	function("kerneltype2string", &kerneltype2string);
	function("string2kerneltype", &string2kerneltype);

	function("addChildNode", &addChildNode);
	function("setIntNodeValue", &setIntNodeValue);
	function("setRealNodeValue", &setRealNodeValue);
	function("setStringNodeValue", &setStringNodeValue);
	function("setVector2dNodeValue", &setVector2dNodeValue);
	function("setVector3dNodeValue", &setVector3dNodeValue);
	function("setVector4dNodeValue", &setVector4dNodeValue);
	function("addIntNodeValue", &addIntNodeValue);
	function("addRealNodeValue", &addRealNodeValue);
	function("addStringNodeValue", &addStringNodeValue);
	function("addVector2dNodeValue", &addVector2dNodeValue);
	function("addVector3dNodeValue", &addVector3dNodeValue);
	function("addVector4dNodeValue", &addVector4dNodeValue);

	function("getNodeIntValue", &getNodeIntValue);
	function("getNodeRealValue", &getNodeRealValue);
	function("getNodeStringValue", &getNodeStringValue);
	function("getNodeVector2dValue", &getNodeVector2dValue);
	function("getNodeVector3dValue", &getNodeVector3dValue);
	function("getNodeVector4dValue", &getNodeVector4dValue);

	function("getNodeIntArrayValue", &getNodeIntArrayValue);
	function("getNodeRealArrayValue", &getNodeRealArrayValue);
	function("getNodeStringArrayValue", &getNodeStringArrayValue);
	function("getNodeVector2dArrayValue", &getNodeVector2dArrayValue);
	function("getNodeVector3dArrayValue", &getNodeVector3dArrayValue);
	function("getNodeVector4dArrayValue", &getNodeVector4dArrayValue);

	function("formatToXmlStream", &udx_formatToXmlStr);
	function("loadFromXmlStream", &udx_loadFromXmlStr);
}